/**
 * Marked Editor
 * 
 */
(function() {
    "use strict";

    if(typeof(console) == "null" || typeof(console) == "undefined") {
        console = {log: function(s) {alert(s);}};
    }

    var namespace = function(name, scope) {
        var a = name.split(".");
        var p = (scope || window);

        for(var i = 0; i < a.length; i++) {
            var n = a[i];

            if(typeof(p[n]) == "undefined") {
                p[n] = {};
            }
            p = p[n];
        }
        return p;
    };

    namespace("com.skin.util");
    namespace("com.skin.upload");
    com.skin.util.namespace = namespace;
})();

(function() {
    "use strict";

    var KeyCode = com.skin.util.KeyCode = {
        "ESC":       27,
        "TAB":       9,
        "CTRL":      17,
        "SHIFT":     16,
        "SPACE":     32,
        "ENTER":     13,
        "BACKSPACE": 8,
        "SCROLL":    145,
        "CAPSLOCK":  20,
        "NUMLOCK":   144,
        "PAUSE":     19,
        "INSERT":    45,
        "HOME":      36,
        "DELETE":    46,
        "END":       35,
        "PAGEUP":    33,
        "PAGEDOWN":  34,
        "LEFT":      37,
        "UP":        38,
        "RIGHT":     39,
        "DOWN":      40,
        "F1":        112,
        "F2":        113,
        "F3":        114,
        "F4":        115,
        "F5":        116,
        "F6":        117,
        "F7":        118,
        "F8":        119,
        "F9":        120,
        "F10":       121,
        "F11":       122,
        "F12":       123
    };

    var Shortcut = com.skin.util.Shortcut = function() {
        this.listeners = [];
    };

    Shortcut.prototype.keydown = function(event) {
        var src = (event.srcElement || event.target);
        var listeners = this.listeners;

        for(var i = 0; i < listeners.length; i++) {
            var listener = listeners[i];
            var shortcut = listener.shortcut;

            if(this.match(shortcut, event) == true) {
                return listener.handler.apply(this.context, [event]);
            }
        }
        return true;
    };

    Shortcut.prototype.match = function(shortcut, event) {
        var a = shortcut.split("+");
        var keyCode = (event.keyCode || event.which);

        if(a.length < 1) {
            return false;
        }

        for(var i = 0; i < a.length; i++) {
            var name = (a[i]).replace(/(^\s*)|(\s*$)/g, "");

            if(name.length < 1) {
                continue;
            }

            if(name == "CTRL") {
                if(event.ctrlKey == true) {
                    continue;
                }
                else {
                    return false;
                }
            }

            if(name == "SHIFT") {
                if(event.shiftKey == true) {
                    continue;
                }
                else {
                    return false;
                }
            }

            if(name == "ALT") {
                if(event.altKey == true) {
                    continue;
                }
                else {
                    return false;
                }
            }

            if(name.length > 1) {
                if(keyCode != KeyCode[name]) {
                    return false;
                }
            }
            else {
                if(keyCode != name.charCodeAt(0)) {
                    return false;
                }
            }
        }
        return true;
    };

    Shortcut.prototype.addListener = function(shortcut, handler) {
        var a = shortcut.split("|");

        for(var i = 0; i < a.length; i++) {
            var shortcut = (a[i]).replace(/(^\s*)|(\s*$)/g, "");

            if(shortcut.length > 0) {
                this.listeners[this.listeners.length] = {"shortcut": shortcut, "handler": handler};
            }
        }
    };

    var e = com.skin.util.EventUtil = {};

    e.bind = function(object, handler) {
        return function(event) {
            return handler.call(object, (event || window.event));
        };
    };

    e.fire = function(element, type, bubbles, cancelable) {
        if(document.createEvent) {
            var event = document.createEvent("Event");
            event.initEvent(type, bubbles !== undefined ? bubbles : true, cancelable !== undefined ? cancelable : false);
            element.dispatchEvent(event);
        }
        else if(document.createEventObject) {
            var event = document.createEventObject();
            element.fireEvent("on" + type, event);
        }
        else if(typeof(element["on" + type]) == "function") {
            element["on" + type]();
        }
    };

    e.addListener = function(target, type, handler) {
        var a = type.split(",");

        for(var i = 0; i < a.length; i++) {
            if(target.attachEvent) {
                target.attachEvent("on" + a[i], handler);
            }
            else if(target.addEventListener) {
                target.addEventListener(a[i], handler, false);
            }
            else {
                target["on" + a[i]] = handler;
            }
        }
    };

    e.removeListener = function(target, type, handler) {
        if(target.detachEvent) {
            target.detachEvent("on" + type, handler);
        }
        else if(target.removeEventListener) {
            target.removeEventListener(type, handler, false);
        }
        else {
            target["on" + type] = null;
        }
    };

    e.cancel = function(event) {
        if(event == null) {
            return false;
        }

        if(event.stop) {
            event.stop();
        }
        else if(event.stopPropagation()) {
            event.stopPropagation();
        }
        else {
            event.cancelBubble = true;
        }

        if(event.preventDefault) {
            event.preventDefault();
        }

        event.cancel = true;
        event.returnValue = false;
        return false;
    };
})();

(function(e) {
    var e = com.skin.util.StringUtil = {};

    e.trim = function(source) {return (source != null ? source.toString().replace(/(^\s*)|(\s*$)/g, "") : "");};
    e.startsWith = function(source, prefix) {
        if(source.length >= prefix.length) {
            return (source.substring(0, prefix.length).toLowerCase() == prefix.toLowerCase());
        }
        return false;
    };

    e.replace = function(source, context) {
        var c;
        var buffer = [];

        for(var i = 0, length = source.length; i < length; i++) {
            c = source.charAt(i);

            if(c == "$" && i < length - 1 && source.charAt(i + 1) == "{") {
                var k = source.indexOf("}", i + 2);

                if(k > -1) {
                    var name = source.substring(i + 2, k);
                    var value = context[name];

                    if(value != null) {
                        buffer[buffer.length] = value;
                    }
                    i = k;
                }
                else {
                    buffer[buffer.length] = source.substring(i + 2);
                    break;
                }
            }
            else {
                buffer[buffer.length] = c;
            }
        }
        return buffer.join("");
    };

    var I18N = com.skin.util.I18N = {};
    var MessageFormat = com.skin.util.MessageFormat = {};

    I18N.load = function(language) {
        if(language != null && language.length > 0) {
            var url = Marked.getHome() + "/lang/" + language + ".js";
            com.skin.util.Loader(document, url);
        }
    };

    I18N.format = MessageFormat.format = function(pattern) {
        var c;
        var buffer = [];
        var args = arguments;

        /**
         * var pattern = "这是一个示例\\{\\}, 这是一个示例{1}, 这是一个示例{2}";
         */
        for(var i = 0, length = pattern.length; i < length; i++) {
            c = pattern.charAt(i);

            if(c == "\\" && i < length - 1) {
                i = i + 1;
                c = pattern.charAt(i);

                if(c == "{" || c == "}") {
                    buffer[buffer.length] = c;
                    continue;
                }
                else {
                    buffer[buffer.length] = "\\";
                    buffer[buffer.length] = c;
                    continue;
                }
            }
            else if(c == "{") {
                var k = pattern.indexOf("}", i + 1);

                if(k > -1) {
                    var index = parseInt(pattern.substring(i + 1, k));

                    if(!isNaN(index) && index > 0 && index < args.length) {
                        buffer[buffer.length] = (args[index] || "");
                    }
                    i = k;
                }
                else {
                    buffer[buffer.length] = pattern.substring(i + 1);
                    break;
                }
            }
            else {
                buffer[buffer.length] = c;
            }
        }
        return buffer.join("");
    };
})();

(function() {
    var StyleUtil = com.skin.util.StyleUtil = {};

    StyleUtil.getTop = function(e) {
        var current = e;
        var top = e.offsetTop;

        while((current = current.offsetParent) !== null){
            top += current.offsetTop;
        }
        return top;
    };

    StyleUtil.getLeft = function(e) {
        var current = e;
        var top = e.offsetLeft;

        while((current = current.offsetParent) !== null){
            top += current.offsetLeft;
        }
        return top;
    };

    StyleUtil.width = function(e) {
        var result = this.getStyle(e, "width");

        if(result != null) {
            result = parseInt(result.replace("px", ""));
        }
        return isNaN(result) ? 0 : result;
    };

    StyleUtil.height = function(e) {
        var result = this.getStyle(e, "height");

        if(result != null) {
            result = parseInt(result.replace("px", ""));
        }
        return isNaN(result) ? 0 : result;
    };

    StyleUtil.getDocumentScrollTop = function(doc) {
        var scrollTop = doc.body.scrollTop;

        if(scrollTop == 0) {
            return doc.documentElement.scrollTop;
        }
        return scrollTop;
    };

    StyleUtil.getDocumentScrollLeft = function(doc) {
        var scrollTop = doc.body.scrollLeft;

        if(scrollTop == 0) {
            return doc.documentElement.scrollLeft;
        }
        return scrollTop;
    };

    StyleUtil.getStyle = function(e, name) {
        if(e.style[name]) {
            return e.style[name];
        }
        else if(document.defaultView != null && document.defaultView.getComputedStyle != null) {
            var computedStyle = document.defaultView.getComputedStyle(e, null);

            if(computedStyle != null) {
                var property = name.replace(/([A-Z])/g, "-$1").toLowerCase();
                return computedStyle.getPropertyValue(property);
            }
        }
        else if(e.currentStyle != null) {
            return e.currentStyle[name];
        }
        return null;
    };

    StyleUtil.hasClass = function(src, name) {
        if(src == null || src.className == null) {
            return false;
        }

        var a = src.className.split(/\s+/);

        for(var i = 0; i < a.length; i++) {
            if(a[i] == name) {
                return true;
            }
        }
        return false;
    };

    StyleUtil.addClass = function(src, name) {
        if(src != null) {
            this.removeClass(src, name);

            if(src.className != null && src.className != "") {
                src.className = src.className + " " + name;
            }
            else {
                src.className = name;
            }
        }
    };

    StyleUtil.removeClass = function(src, name) {
        if(src != null) {
            var className = src.className;

            if(className != null && className != "") {
                var b = [];
                var a = className.split(/\s+/);

                for(var i = 0; i < a.length; i++) {
                    var c = (a[i]).replace(/(^\s*)|(\s*$)/g, "");

                    if(c.length > 0 && c != name) {
                        b[b.length] = c;
                    }
                }
                src.className = b.join(" ");
            }
        }
    };

    var DOM = com.skin.util.DOM = {};

    DOM.getSelected = function(element) {
        if(element == null) {
            return;
        }

        if(!window.getSelection) { 
            return document.selection.createRange().text;
        }
        else{
            return element.value.substring(element.selectionStart, element.selectionEnd);
        }
    };

    DOM.replace = function(element, value, start, end) {
        element.focus();

        if(element.createTextRange) {
            var range = document.selection.createRange().duplicate();
            document.selection.empty();
            range.text = value;
        }
        else if(element.setSelectionRange) {
            var rangeStart = element.selectionStart;
            var rangeEnd = element.selectionEnd;
            var str1 = element.value.substring(0, rangeStart);
            var str2 = element.value.substring(rangeEnd);
            element.value = str1 + value + str2;

            if(start == null) {
                start = 0;
            }

            if(end == null || end == 0) {
                end = value.length;
            }

            if(end < 0) {
                end = value.length + end;
            }

            element.selectionStart = rangeStart + start;
            element.selectionEnd = rangeStart + end;
            // element.blur();
        }
    };
})();

(function() {
    var Marked = window.Marked = {};
    Marked.version = "1.0.0";
    Marked.tools   = [];
    Marked.plugins = {};
    Marked.context = {};
    Marked.trim = function(source) {return (source != null ? source.toString().replace(/(^\s*)|(\s*$)/g, "") : "");};
    Marked.getHome = function() {
        if(Marked.home == null) {
            var home = null;
            var scripts = document.getElementsByTagName("script");

            for(var i = 0, length = scripts.length; i < length; i++) {
                var src = scripts[i].src;

                if(src != null && src != undefined && src.length > 0) {
                    if(src.match(/md[^\/]*\.js/i)) {
                        home = src.replace(/md[^\/]*\.js/, "");
                        break;
                    }
                }
            }

            if(home == null) {
                Marked.home = "";
            }
            else {
                home = Marked.trim(home);

                if(home.length >= 1) {
                    if(home.substring(home.length - 1) == "/") {
                        home = home.substring(0, home.length - 1);
                    }
                }
                Marked.home = home;
            }
        }
        return Marked.home;
    };

    Marked.setInstance = function(instance) {
        Marked.context[instance.instanceId] = instance;
    };

    Marked.getInstance = function(src) {
        var id = null;

        if(src == null || src == "undefined") {
            return;
        }

        if(typeof(src) == "string") {
            id = src;
        }
        else {
            id = src.getAttribute("editorId");
        }
        return Marked.context[id];
    };

    Marked.load = function(url) {
        var e = document.createElement("script");
        e.type = "text/javascript";
        e.src = url;
        document.body.appendChild(e);
    };

    Marked.plugin = function(plugin) {
        if(plugin != null) {
            var name = plugin.name;
            this.plugins[name] = plugin;
        }
    };

    Marked.getPlugin = function(name) {
        return (Marked.getPlugins())[name];
    };

    Marked.getPlugins = function() {
        return this.plugins;
    };
})();

(function() {
    var ID = com.skin.util.ID = {};
    var StyleUtil = com.skin.util.StyleUtil;
    var StringUtil = com.skin.util.StringUtil;

    ID.next = function() {
        if(this.seed == null) {
            this.seed = 0;
        }

        this.seed++;
        return this.seed;
    };

    var Parser = Marked.Parser = function() {
    };

    Marked.Editor = function() {
        this.id = ID.next();
        this.instanceId = "md_container" + this.id;
        this.toolbarId  = "md-toolbar-"  + this.id;
        this.viewBodyId = "md-viewbody-" + this.id;
        this.textareaId = "md-textarea-" + this.id;
        this.markViewId = "md-markview-" + this.id;

        this.shortcuts = {};
        this.i18n = Marked.I18N;
        Marked.setInstance(this);
    };

    var e = Marked.Editor.prototype;

    e.create = function(options) {
        var a = ("bold,italic,header,link,image,emot,ulist,olist,hr,code,quote,preview,fullscreen").split(",");
        var m = (Marked.tools || []);
        var t = (options.target != null ? document.getElementById(options.target) : null);

        if(t == null) {
            return;
        }

        var b = [];
        b[b.length] = "<div id=\"" + this.toolbarId + "\" class=\"md-toolbar\" unselectable=\"on\">";

        for(var i = 0; i < a.length; i++) {
            var e = m[a[i]];

            if(e != null) {
                var title = StringUtil.replace(e.title, this.i18n);

                if(e.shortcut != null && e.shortcut != "") {
                    this.shortcuts[e.shortcut] = e.command;
                    title = title + " (" + e.shortcut + ")";
                }

                b[b.length] = "<a class=\"md-button " + a[i]+ " enabled\" href=\"javascript:void(0)\""
                    + "tabindex=\"-1\" unselectable=\"on\" command=\"" + e.name + "\" title=\"" + title + "\"></a>";
            }
        }

        b[b.length] = "</div>";
        b[b.length] = "<div id=\"" + this.viewBodyId + "\" class=\"md-view-body\">";
        b[b.length] =     "<textarea id=\"" + this.textareaId + "\" class=\"md-textarea\" spellcheck=\"false\"></textarea>";
        b[b.length] =     "<div id=\"" + this.markViewId + "\" class=\"md-mark-view\"></div>";
        b[b.length] = "</div>";

        var c = document.createElement("div");
        c.id = this.instanceId;
        c.className = "md-container";
        c.innerHTML = b.join("");
        t.appendChild(c);

        var self = this;

        setTimeout(function() {
            self.setup(Marked.plugins);
            self.setContent(options.content);
            self.resize();
        }, 300);
        return this;
    };

    e.dispatch = function(command) {
        if(command == null) {
            return false;
        }

        var tool = Marked.tools[command];

        if(tool == null) {
            return false;
        }

        if(tool.click != null) {
            var args = [this].concat([].slice.call(arguments, 1));
            tool.click.apply(tool, args);
            return true;
        }

        if(tool.execute != null) {
            var args = [this].concat([].slice.call(arguments, 1));
            tool.execute.apply(tool, args);
            return true;
        }
        return false;
    };

    e.execute = function(command) {
        var tool = Marked.tools[command];

        if(tool != null) {
            var args = [this].concat([].slice.call(arguments, 1));
            tool.execute.apply(tool, args);
        }
    },

    /**
     * 安装插件
     */
    e.setup = function(plugins) {
        for(var name in plugins) {
            var plugin = plugins[name];

            if(plugin != null && plugin.execute != null) {
                plugin.execute(this);
            }
        }
    };

    e.getPlugin = function(command) {
        return (Marked.getPlugins())[command];
    };

    e.getContainer = function() {
        return document.getElementById(this.instanceId);
    };

    e.getToolbar = function() {
        return document.getElementById(this.toolbarId);
    };

    e.getViewBody = function() {
        return document.getElementById(this.viewBodyId);
    };

    e.getTextarea = function() {
        return document.getElementById(this.textareaId);
    };

    e.getMarkView = function() {
        return document.getElementById(this.markViewId);
    };

    e.render = function() {
        var t = this.getTextarea();
        var v = this.getMarkView();
        v.innerHTML = "<div style=\"margin: 0px 0px 0px 20px; padding: 0px 0px 0px 10px; border-left: 1px dashed #bbbbbb; overflow: hidden;\">" + marked(t.value, {breaks: true}) + "</div>";
    };

    e.setContent = function(content) {
        var textarea = this.getTextarea();
        textarea.value = (content || "");
        textarea.style.height = textarea.scrollHeight + "px";
    };

    e.getContent = function() {
        return this.getTextarea().value;
    };

    e.resize = function() {
        var c = this.getContainer();
        var v = this.getViewBody();
        var t = this.getTextarea();
        v.style.width = "100%";
        v.style.height = (c.clientHeight - this.getToolbar().clientHeight) + "px";
        t.style.height = t.scrollHeight + "px";
    };

    e.fullscreen = function() {
        var c = this.getContainer();
        var v = this.getViewBody();

        if(StyleUtil.hasClass(c, "fullscreen")) {
            this.model = 1;
            v.className = "md-view-body";
            c.className = "md-container";
            this.resize();
        }
        else {
            this.model = 2;
            this.render();
            v.className = "md-full-body";
            c.className = "md-container fullscreen";
            this.resize();
        }
    };
})();

(function() {
    var e = Marked.UploadDialog = {editor: null};

    e.getContainer = function() {
        var c = document.getElementById("md-upload-dialog");

        if(c == null) {
            c = document.createElement("div");
            c.id = "md-upload-dialog";
            c.className = "md-mask";
            c.innerHTML = [
                "<div class=\"md-dialog\">",
                    "<div class=\"md-dialog-header\"><h3>图片/附件</h3><span id=\"md-upload-close\" class=\"close\"></span></div>",
                    "<div class=\"md-dialog-body\">",
                        "<div class=\"md-label\">请输入图片或附件地址</div>",
                        "<div>",
                            "<i class=\"icon-image\"></i><input id=\"md-image-url\" type=\"text\" class=\"md-image-url\" placeholder=\"http://example.com/images/diagram.jpg &quot;可选标题&quot;\" value=\"http://www.test.com/1.gif\"/>",
                        "</div>",
                        "<div><a id=\"md-upload-button\" class=\"upload-button\" href=\"javascript:void(0)\"><i class=\"icon-cloud-upload\"></i> 上传本地图片或附件...</a></div>",
                        "<div style=\"margin-top: 10px;\"><strong>提示：</strong>截屏或复制图像数据到剪切板后，可在编辑区按 Ctrl+V 一键粘贴上传。也可以直接拖拽文件到编辑区。</div>",
                    "</div>",
                    "<div class=\"md-dialog-footer\">",
                        "<button id=\"md-upload-cancel\" class=\"md-button md-cancel\">取消(ESC)</button>",
                        "<button id=\"md-upload-ensure\" class=\"md-button md-ensure\">确定(Enter)</button>",
                    "</div>",
                "</div>"].join("");
            document.body.appendChild(c);

            var EventUtil = com.skin.util.EventUtil;

            EventUtil.addListener(document.getElementById("md-upload-button"), "click", function(event) {
                if(Marked.uploader == null || Marked.uploader == undefined) {
                    alert("上传组件未注册。");
                    return true;
                }

                Marked.uploader.open(function(url) {
                    document.getElementById("md-image-url").value = url;
                });
            });

            EventUtil.addListener(document.getElementById("md-upload-close"), "click", function(event) {
                Marked.UploadDialog.close();
            });

            EventUtil.addListener(document.getElementById("md-upload-cancel"), "click", function(event) {
                Marked.UploadDialog.close();
            });

            EventUtil.addListener(document.getElementById("md-upload-ensure"), "click", function(event) {
                var title = "输入图片标题";
                var url = document.getElementById("md-image-url").value;

                if(url.length < 1) {
                    alert("请输入图片/附件的地址。");
                    return;
                }

                var k = url.indexOf("\"");

                if(k > -1) {
                    title = url.substring(k + 1);
                    url = url.substring(0, k -1);
                }

                Marked.UploadDialog.editor.execute("image", url, title.replace("\"", ""), true);
                Marked.UploadDialog.close();
            });
        }
        return c;
    };

    e.open = function(editor) {
        this.editor = editor;
        this.getContainer().style.display = "block";
    };

    e.close = function() {
        this.editor = null;
        this.getContainer().style.display = "none";
    }
})();

(function() {
    var home = Marked.getHome();
    var language = (window.navigator.language || navigator.browserLanguage).toLowerCase();

    document.write("<link type=\"text/css\" rel=\"stylesheet\" href=\"" + home + "/css/md.css\"/>");
    document.write("<script type=\"text/javascript\" src=\"" + home + "/marked.min.js\"></script>");
    document.write("<script type=\"text/javascript\" src=\"" + home + "/lang/" + language + ".js\"></script>");
})();

Marked.tools["bold"] = (function() {
    return {
        "name": "bold",
        "shortcut": "CTRL + B",
        "title": "${tool.bold}",
        "execute": function(editor) {
            var textarea = editor.getTextarea();
            var content = com.skin.util.DOM.getSelected(textarea);

            if(content == null || content.length < 1) {
                com.skin.util.DOM.replace(textarea, " **粗体** ", 3, -3);
                return;
            }
            com.skin.util.DOM.replace(textarea, " **" + content + "** ", 3, -3);
        }
    };
})();

Marked.tools["italic"] = (function() {
    return {
        "name": "italic",
        "shortcut": "CTRL + I",
        "title": "${tool.italic}",
        "execute": function(editor) {
            var textarea = editor.getTextarea();
            var content = com.skin.util.DOM.getSelected(textarea);

            if(content == null || content.length < 1) {
                com.skin.util.DOM.replace(textarea, " _斜体_ ", 2, -2);
                return;
            }
            com.skin.util.DOM.replace(textarea, " _" + content + "_ ", 2, -2);
        }
    };
})();

Marked.tools["header"] = (function() {
    return {
        "name": "header",
        "shortcut": "CTRL + H",
        "title": "${tool.header}",
        "execute": function(editor) {
            var textarea = editor.getTextarea();
            var content = com.skin.util.DOM.getSelected(textarea);

            if(content == null || content.length < 1) {
                com.skin.util.DOM.replace(textarea, "### 标题", 4);
                return;
            }
            com.skin.util.DOM.replace(textarea, "### " + content, 4);
        }
    };
})();

Marked.tools["link"] = (function() {
    return {
        "name": "link",
        "shortcut": "CTRL + L",
        "title": "${tool.link}",
        "execute": function(editor) {
            var textarea = editor.getTextarea();
            var content = com.skin.util.DOM.getSelected(textarea);

            if(content == null || content.length < 1) {
                com.skin.util.DOM.replace(textarea, "[输入链接说明](http://)", 1, 7);
                return;
            }
            com.skin.util.DOM.replace(textarea, "[" + content + "](http://)", content.length + 10, content.length + 10);
        }
    };
})();

Marked.tools["image"] = (function() {
    return {
        "name": "image",
        "title": "${tool.image}",
        "click": function(editor) {
            Marked.UploadDialog.open(editor);
        },
        "execute": function(editor, url, title, select) {
            var textarea = editor.getTextarea();
            var content = "![" + title + "](" + url + " \"" + title + "\")";

            if(!select) {
                com.skin.util.DOM.replace(textarea, content, content.length, content.length);
            }
            else {
                com.skin.util.DOM.replace(textarea, content, 2, 8);
            }
        }
    };
})();

Marked.tools["emot"] = (function() {
    return {
        "name": "emot",
        "title": "${tool.emot}",
        "execute": function(editor) {
            var textarea = editor.getTextarea();
            com.skin.util.DOM.replace(textarea, " :smile: ", 9, 9);
        }
    };
})();

Marked.tools["ulist"] = (function() {
    return {
        "name": "ulist",
        "title": "${tool.ulist}",
        "execute": function(editor) {
            var textarea = editor.getTextarea();
            var content = com.skin.util.DOM.getSelected(textarea);

            if(content == null || content.length < 1) {
                com.skin.util.DOM.replace(textarea, "- 这里是列表文本", 2);
                return;
            }
            com.skin.util.DOM.replace(textarea, "- " + content, 2);
        }
    };
})();

Marked.tools["olist"] = (function() {
    return {
        "name": "olist",
        "title": "${tool.olist}",
        "execute": function(editor) {
            var textarea = editor.getTextarea();
            var content = com.skin.util.DOM.getSelected(textarea);

            if(content == null || content.length < 1) {
                com.skin.util.DOM.replace(textarea, "1. 这里是列表文本", 3);
                return;
            }
            com.skin.util.DOM.replace(textarea, "1. " + content, 3);
        }
    };
})();

Marked.tools["hr"] = (function() {
    return {
        "name": "hr",
        "title": "${tool.hr}",
        "execute": function(editor) {
            var textarea = editor.getTextarea();
            var content = "\n==========================\n";
            com.skin.util.DOM.replace(textarea, "\n==========================\n", content.length + 1, content.length + 1);
        }
    };
})();

Marked.tools["code"] = (function() {
    return {
        "name": "code",
        "title": "${tool.code}",
        "execute": function(editor) {
            var textarea = editor.getTextarea();
            var content = com.skin.util.DOM.getSelected(textarea);

            if(content == null || content.length < 1) {
                com.skin.util.DOM.replace(textarea, "```\n这里输入代码\n```\n", 4, -4);
                return;
            }
            com.skin.util.DOM.replace(textarea, "```\n" + content + "\n```\n", 4, -4);
        }
    };
})();

Marked.tools["quote"] = (function() {
    return {
        "name": "quote",
        "title": "${tool.quote}",
        "execute": function(editor) {
            var textarea = editor.getTextarea();
            var content = com.skin.util.DOM.getSelected(textarea);

            if(content == null || content.length < 1) {
                com.skin.util.DOM.replace(textarea, "> 这里输入引用文本", 2);
                return;
            }
            com.skin.util.DOM.replace(textarea, "> " + content, 2);
        }
    };
})();

Marked.tools["preview"] = (function() {
    return {
        "name": "preview",
        "title": "${tool.preview}",
        "execute": function(editor) {
        }
    };
})();

Marked.tools["fullscreen"] = (function() {
    return {
        "name": "fullscreen",
        "title": "${tool.fullscreen}",
        "execute": function(editor) {
            editor.fullscreen();
        }
    };
})();

/**
 * 系统插件 - 工具栏
 */
Marked.plugin({name: "md-plugin1", "execute": function(editor) {
    var toolbar = editor.getToolbar();
    var textarea = editor.getTextarea();

    var KeyCode = com.skin.util.KeyCode;
    var EventUtil = com.skin.util.EventUtil;
    var StyleUtil = com.skin.util.StyleUtil;

    EventUtil.addListener(window, "resize", function(event) {
        editor.resize();
    });

    EventUtil.addListener(toolbar, "click", function(event) {
        var src = (event.srcElement || event.target);
        var name = src.getAttribute("command");

        if(name == null) {
            return false;
        }

        if(StyleUtil.hasClass(src, "disabled")) {
            return false;
        }

        var command = Marked.tools[name];

        if(command == null) {
            return false;
        }

        if(command.click != null) {
            command.click(editor);
            return true;
        }

        if(command.execute != null) {
            command.execute(editor);
            return true;
        }
        return false;
    });

    EventUtil.addListener(textarea, "keyup", function(event) {
        var c = editor.getContainer();

        if(StyleUtil.hasClass(c, "fullscreen")) {
            editor.render();
        }
        else {
            textarea.style.height = (textarea.scrollHeight) + "px";
        }
    });

    /**
     * 系统插件 - 快捷键
     */
    var shortcut = (function() {
        var tools = Marked.tools;
        var shortcut = new com.skin.util.Shortcut();

        for(var name in tools) {
            var tool = tools[name];
            var key = tool.shortcut;

            if(key != null && key != undefined) {
                var hander = (function(obj, n) {
                    return function() {
                        obj.dispatch(n);
                    };
                })(editor, tool.name);

                shortcut.addListener(key, hander);
            }
        }
        return shortcut;
    })();

    EventUtil.addListener(textarea, "keydown", function(event) {
        var flag = shortcut.keydown(event);

        if(flag == true) {
            return true;
        }
        EventUtil.cancel(event);
        return false;
    });

    /**
     * 同步滚动
     * 只有当textarea滚动时才同步
     * 预览滚动时不同步
     */
    EventUtil.addListener(textarea, "scroll", function(event) {
        var markView = editor.getMarkView();
        markView.scrollTop = textarea.scrollTop;
    });
}});

/**
 * 系统插件 - CTRL + V上传
 */
Marked.plugin({name: "md-plugin2", "execute": function(editor) {
    var toolbar = editor.getToolbar();
    var textarea = editor.getTextarea();

    var KeyCode = com.skin.util.KeyCode;
    var EventUtil = com.skin.util.EventUtil;
    var StyleUtil = com.skin.util.StyleUtil;

    /**
     * 粘贴截图
     */
    EventUtil.addListener(textarea, "paste", function(event) {
        var clipboard = event.clipboardData;
        var items = clipboard.items;

        if(items == null || items.length < 1) {
            return true;
        }

        if(Marked.uploader == null || Marked.uploader == undefined) {
            console.log("上传组件未注册。");
            return true;
        }

        var files = [];

        for(var i = 0, length = items.length; i < length; i++) {
            var item = items[i];

            if(item.kind == "file" || item.type.indexOf("image") > -1) {
                var file = item.getAsFile();
                file.name = "blob." + item.type.replace("image/", "");
                files.push(file);
            }
        }

        Marked.uploader.select(files, function(url) {
            editor.execute("image", url, "输入图标标题", false);
        });
        return false;
    });

    /**
     * 拖拽文件支持
     */
    EventUtil.addListener(textarea, "drop", function(event) {
        if(event.dataTransfer == null || event.dataTransfer.files == null || event.dataTransfer.files.length < 1) {
            return true;
        }

        if(Marked.uploader == null || Marked.uploader == undefined) {
            console.log("上传组件未注册。");
            return true;
        }

        Marked.uploader.select(event.dataTransfer.files, function(url) {
            editor.execute("image", url, "输入图标标题", false);
        });
        EventUtil.cancel(event);
    });

}});

(function() {
    /**
     * 注: JEditor并不依赖于jQuery, 这里只是提供一种简便的创建JEditor的方法.
     * 如果你使用了jQuery, 只需要使用jQuery("#my_textarea_id").jeditor()即可.
     */
    if(typeof(jQuery) != null && typeof(jQuery) != "undefined") {
        jQuery.fn.extend({
            marked: function() {
                jQuery(this).each(function() {
                    var textarea = jQuery(this);

                    var jeditor = new Marked.Editor();
                    var id = "marked_inst_" + jeditor.id;
                    var toolbar = textarea.attr("toolbar");

                    textarea.hide();
                    textarea.after("<div id=\"" + id + "\" style=\"height: 100%;\"></div>");

                    var options = {target: id, content: textarea.val()};

                    if(toolbar != null) {
                        options.toolbar = toolbar;
                    }
                    textarea.attr("editorId", jeditor.instanceId);
                    jeditor.create(options);
                });
            },
            fullscreen: function() {
                var textarea = jQuery(this).get(0);
                var instance = Marked.getInstance(textarea);
                instance.fullscreen();
            }
        });
    }
})();

